﻿using System.Net;
using System.Net.Sockets;
using System.Threading;
using RemoteDesktop.Client.Data;

namespace RemoteDesktop.Client.Core
{
    /// <summary>
    /// Provides methods to start/stop a server.
    /// </summary>
    internal class Server
    {
        //**************************************************
        //
        // Dependencies
        //
        //**************************************************

        #region Dependencies

        /// <summary>
        /// Gets config of the client-side.
        /// </summary>
        private readonly ClientConfig _config;

        /// <summary>
        /// Gets the logger instance.
        /// </summary>
        private readonly ILog _log;

        #endregion


        //**************************************************
        //
        // Constants
        //
        //**************************************************

        #region Constants

        /// <summary>
        /// Gets sleep time in ms.
        /// </summary>
        private const int SleepTime = 1000;

        #endregion



        //**************************************************
        //
        // Private variables
        //
        //**************************************************

        #region Private variables


        #endregion


        //**************************************************
        //
        // Constructors
        //
        //**************************************************

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object"/> class.
        /// </summary>
        public Server(ClientConfig config, ILog log)
        {
            _config = config;
            _log = log;
        }

        #endregion


        //**************************************************
        //
        // Public methods
        //
        //**************************************************

        #region Public methods

        /// <summary>
        /// Starts the server.
        /// </summary>
        public void Start()
        {
            Thread thread = new Thread(this.RunBackgroundThread)
                {
                    Name = this.GetType().FullName,
                    IsBackground = true,
                    Priority = ThreadPriority.BelowNormal
                };
            thread.Start();
        }

        #endregion


        //**************************************************
        //
        // Private methods
        //
        //**************************************************

        #region Private methods

        /// <summary>
        /// Runs the background thread code.
        /// </summary>
        private void RunBackgroundThread()
        {
            // start server
            _log.Write("Starting server on port {0}...", _config.TunnelApplicationPort);
            var listener = new TcpListener(IPAddress.Any, _config.TunnelApplicationPort);
            listener.Start();

            // wait
            while (true)
            {
                // sleep a moment
                Thread.Sleep(SleepTime);

                // check available pending connection
                if (!listener.Pending())
                {
                    // no pending, just sleep again
                    continue;
                }

                // accept connection
                TcpClient client = listener.AcceptTcpClient();
                new Transmitter(_config, _log, client).Start();
            }
            // ReSharper disable FunctionNeverReturns
        }
        // ReSharper restore FunctionNeverReturns

        #endregion

    }
}